#include "stdafx.h"
#include "extern.h"
#include <stdio.h>
#include <wchar.h>
#include "database.h"
#include <string>

#include<windows.h>
#include<direct.h>


#include "log.h"
const unsigned int LOGPORT = 7001;


#ifdef WIN32
int gettimeofday(struct timeval *tp, void *tzp)
{
  time_t clock;
  struct tm tm;
  SYSTEMTIME wtm;
  GetLocalTime(&wtm);
  tm.tm_year   = wtm.wYear - 1900;
  tm.tm_mon   = wtm.wMonth - 1;
  tm.tm_mday   = wtm.wDay;
  tm.tm_hour   = wtm.wHour;
  tm.tm_min   = wtm.wMinute;
  tm.tm_sec   = wtm.wSecond;
  tm. tm_isdst  = -1;
  clock = mktime(&tm);
  tp->tv_sec = clock;
  tp->tv_usec = wtm.wMilliseconds * 1000;
  return (0);
}
#endif


//char g_NowTime[32] = {0};
//getMyTool2=new myTool();
int getNowYearMonth(char * nowYearMonth)
{
	memset(nowYearMonth, 0, 6);
	char acYear[5] = {0};
	char acMonth[5] = {0};

	time_t now;
    struct tm* timenow;
    
    time(&now);
    timenow = localtime(&now);

    strftime(acYear,sizeof(acYear),"%Y",timenow);
    strftime(acMonth,sizeof(acMonth),"%m",timenow);

	strncat(nowYearMonth, acYear, 4);
	strncat(nowYearMonth, acMonth, 2);
	
	return 0;

}
int getNowTime(char * nowTime)
{
	
	//首先要清空数组
	//char *nowTime = new char[32];
	//char nowTime[19] = {0};
	memset(nowTime, 0, 32);
	char acYear[5] = {0};
	char acMonth[5] = {0};
	char acDay[5] = {0};
	char acHour[5] = {0};
	char acMin[5] = {0};
	char acSec[5] = {0};

	time_t now;
    struct tm* timenow;
    
    time(&now);
    timenow = localtime(&now);

    strftime(acYear,sizeof(acYear),"%Y",timenow);
    strftime(acMonth,sizeof(acMonth),"%m",timenow);
    strftime(acDay,sizeof(acDay),"%d",timenow);
    strftime(acHour,sizeof(acHour),"%H",timenow);
    strftime(acMin,sizeof(acMin),"%M",timenow);
    strftime(acSec,sizeof(acSec),"%S",timenow);

	
	strncat(nowTime, acYear, 4);
	strncat(nowTime, "-", 1);
	strncat(nowTime, acMonth, 2);
	strncat(nowTime, "-", 1);
	strncat(nowTime, acDay, 2);
	strncat(nowTime, " ", 1);
	strncat(nowTime, acHour, 2);
	strncat(nowTime, ":", 1);
	strncat(nowTime, acMin, 2);
	strncat(nowTime, ":", 1);
	strncat(nowTime, acSec, 2);
	strncat(nowTime, "\0", 1);
	return 0;
}
int getNowTimeNoSpace(char * nowTime)
{
	
	//首先要清空数组
	//char *nowTime = new char[32];
	//char nowTime[19] = {0};
	memset(nowTime, 0, 18);

	struct tm *tm_t;
    struct timeval time;
    
    gettimeofday(&time,NULL);
    tm_t = localtime(&time.tv_sec);
    if(NULL != tm_t) {
        sprintf(nowTime,"%04d%02d%02d%02d%02d%02d%03ld",
            tm_t->tm_year+1900,
            tm_t->tm_mon+1, 
            tm_t->tm_mday,
            tm_t->tm_hour, 
            tm_t->tm_min, 
            tm_t->tm_sec,
            time.tv_usec/1000);
    }
	strncat(nowTime, "\0", 1);
	return 0;
}
string getNowTime()
{
//首先要清空数组
	char *nowTime = new char[32];
	//char nowTime[19] = {0};
	memset(nowTime, 0, 32);
	char acYear[5] = {0};
	char acMonth[5] = {0};
	char acDay[5] = {0};
	char acHour[5] = {0};
	char acMin[5] = {0};
	char acSec[5] = {0};

	time_t now;
    struct tm* timenow;
    
    time(&now);
    timenow = localtime(&now);

    strftime(acYear,sizeof(acYear),"%Y",timenow);
    strftime(acMonth,sizeof(acMonth),"%m",timenow);
    strftime(acDay,sizeof(acDay),"%d",timenow);
    strftime(acHour,sizeof(acHour),"%H",timenow);
    strftime(acMin,sizeof(acMin),"%M",timenow);
    strftime(acSec,sizeof(acSec),"%S",timenow);

	strncat(nowTime, acYear, 4);
	strncat(nowTime, "-", 1);
	strncat(nowTime, acMonth, 2);
	strncat(nowTime, "-", 1);
	strncat(nowTime, acDay, 2);
	strncat(nowTime, " ", 1);
	strncat(nowTime, acHour, 2);
	strncat(nowTime, ":", 1);
	strncat(nowTime, acMin, 2);
	strncat(nowTime, ":", 1);
	strncat(nowTime, acSec, 2);
	strncat(nowTime, "\0", 1);
	string rstr;
	for (int i=0;i<strlen(nowTime);++i)
	{
		rstr+=nowTime[i];
	}
	delete[]nowTime;
	nowTime = 0;
	return rstr;

}
bool checkRelaPath(string rootDir,string strFullName)
{
	if (strFullName.empty())
	{
		return false;
	}

	int iPos1;
	int iPos2;
	iPos1 = strFullName.find_last_of('\\') + 1;
	iPos2 = strFullName.find_last_of('/') + 1;

	int iPos = __max(iPos1,iPos2);

	if (iPos <= 0)
	{
		return true;//没有路径表示直接传文件到相对路径
	}
	if(access((rootDir+"/"+strFullName.substr(0, iPos)).c_str(),0)==0)
	{
		//存在目录直接返回true
		//printf("FHL %s >>存在目录%s \n",getNowTime(),(rootDir+"/"+strFullName.substr(0, iPos)).c_str());
		return true;	
	}else{
		//不存在 建立路径 eg:  123/1234/
		strFullName = strFullName.substr(0, iPos);
		while(1)
		{
			//每次循环都减去一层 知道strfullname长度是0 就退出
			if(strlen(strFullName.c_str()) == 0)
			{
				break;
			}
			iPos1 = strFullName.find('\\');
			iPos2 = strFullName.find('/');
			iPos = __max(iPos1,iPos2);
			rootDir = rootDir+"/"+strFullName.substr(0, iPos);
			strFullName = strFullName.substr(iPos+1,strFullName.length() - iPos-1);
			//判断是否存在
			if(access(rootDir.c_str(),0)==-1)
			{
			
				if(mkdir(rootDir.c_str())!=0)
				{
					getMyTool()->printStr("创建目录%s 失败",rootDir.c_str());
					return false;
				}else{
					getMyTool()->printStr("create path:%s",rootDir.c_str());
				}
			}
				
		}
		return true;
	}
	
	
		//access()

	//return strFullName.substr(iPos, strFullName.length() - iPos);
}
int getProgramPath(char* realPath)
{
	GetModuleFileName(NULL, realPath, 512);
	string tmp = realPath;
	int iPos1;
	int iPos2;
	iPos1 = tmp.find_last_of('\\') ;
	iPos2 = tmp.find_last_of('/') ;

	int iPos = __max(iPos1,iPos2);
	strcpy(realPath,tmp.substr(0, iPos).c_str());
	return 0;
    
}
string getSavePath(string rootDir,string strFullName)
{
	if (strFullName.empty())
	{
		return "";
	}

	int iPos1;
	int iPos2;
	iPos1 = strFullName.find_last_of('\\') + 1;
	iPos2 = strFullName.find_last_of('/') + 1;

	int iPos = __max(iPos1,iPos2);

	if (iPos <= 0)
	{
		return rootDir;//没有路径表示直接传文件到相对路径
	}
	if(access((rootDir+"/"+strFullName.substr(0, iPos)).c_str(),0)==0)
	{
		//存在目录直接返回true
		//printf("FHL %s >>存在目录%s \n",getNowTime(),(rootDir+"/"+strFullName.substr(0, iPos)).c_str());
		return rootDir+"/"+strFullName.substr(0, iPos-1);	
	}else{
		//不存在 建立路径 eg:  123/1234/
		strFullName = strFullName.substr(0, iPos);
		string realrootpath = rootDir;
		string realstrFullName = strFullName.substr(0, iPos-1);
		while(1)
		{
			//每次循环都减去一层 知道strfullname长度是0 就退出
			if(strlen(strFullName.c_str()) == 0)
			{
				break;
			}
			iPos1 = strFullName.find('\\');
			iPos2 = strFullName.find('/');
			iPos = __max(iPos1,iPos2);
			rootDir = rootDir+"/"+strFullName.substr(0, iPos);
			strFullName = strFullName.substr(iPos+1,strFullName.length() - iPos-1);
			//判断是否存在
			if(access(rootDir.c_str(),0)==-1)
			{
//				char NowTime[32]={0};
//				getNowTime(NowTime);
				if(mkdir(rootDir.c_str())!=0)
				{
					getMyTool()->printStr("创建目录%s 失败\n",rootDir.c_str());
					return realrootpath;
				}else{
					getMyTool()->printStr("create path:%s\n",rootDir.c_str());
				}
			}
				
		}
		return realrootpath+"/"+realstrFullName;
	}
	
	
		//access()

	//return strFullName.substr(iPos, strFullName.length() - iPos);
}

DWORD MyGetTick()
{
#if WIN32
	return GetTickCount();
#else
	struct timeval tv = {0};
	gettimeofday(&tv, NULL);
	return (UDP_LONG)(tv.tv_sec*1000 + tv.tv_usec / 1000);
#endif
}
void UpdateSpeed2( IUdxTcp * pSocket)
{
	IUdxInfo* pInfo = pSocket->GetUdxInfo();

	char buff1[256] = {0};
	char buff2[256] = {0};
	char buff3[256] = {0};
	char buff4[256] = {0};
	pInfo->GetSpeedStr(buff1,TRUE,true);
	pInfo->GetSpeedStr(buff2,TRUE);
	pInfo->GetSpeedStr(buff3,FALSE,true);
	pInfo->GetSpeedStr(buff4,FALSE);

	char buff[256] = {0};



	if ( RELEASEFOR == "EN")
	{
		sprintf(buff,"speed[cur:%s/avg:%s] recive[cur:%s/avg:%s]  ttl:%d - loss:%0.2f - limit:%llu",
	buff1,buff2,buff3,buff4,pInfo->m_ttl,pInfo->GetLostRate(),pInfo->m_SendBewControl);
	}else if(RELEASEFOR == "CH"){
			sprintf(buff,"发送速度[当前:%s-平均:%s] 接收[当前:%s-平均:%s]  ttl:%d - 丢包:%0.2f - 带宽控制:%llu",
	buff1,buff2,buff3,buff4,pInfo->m_ttl,pInfo->GetLostRate(),pInfo->m_SendBewControl);
	}


	GetUdxTools()->DBGStr("%s\n",buff);
	getMyTool()->printStr(buff);
}
void UpdateSpeed( IUdxTcp * pSocket)
{
	static int lasttime = MyGetTick();
	if(MyGetTick() - lasttime < 1000)
		return;
	
	lasttime = MyGetTick();	

	UpdateSpeed2(pSocket);
}
void UpdateFileTrans(UINT64 fileLength,UINT64 transdLength)
{
	static int lasttime = MyGetTick();//局部静态变量 再次调用时不再初始化
	if(MyGetTick() - lasttime < 1000)
		return;
	
	static UINT64 lastTransdLength = transdLength;
	//如果新的文件长度大于 之前的 则显示速度
	if (transdLength>lastTransdLength)
	{
		
		if ( RELEASEFOR == "EN")
		{
			getMyTool()->printStr("have sent:%I64u%%%%  [%s] ",transdLength*100/fileLength,
			ToString((transdLength-lastTransdLength)*1000/(MyGetTick() - lasttime)).c_str());
		}else if(RELEASEFOR == "CH"){

			getMyTool()->printStr("文件处理进度%I64u%%%%:[%s] ",transdLength*100/fileLength,
			ToString((transdLength-lastTransdLength)*1000/(MyGetTick() - lasttime)).c_str());
		}
		
		
			
	}
	lastTransdLength = transdLength;
	lasttime = MyGetTick();
}
//速度字符串
string ToString(UINT64 speed)
{
	
	string _strSpeed;
	char tspeed[30];
	memset(tspeed,0,sizeof(tspeed));

	if (speed <= 0)
	{
		return _T("0 B/s");
	}
	else if (speed < KB)		//字节
	{	
		sprintf(tspeed,"%I64u B / s",speed);
		
	}
	else if ( (speed >= KB) && (speed < MB) )		//KB
	{
		speed = speed / KB;
		sprintf(tspeed,"%I64u KB / s",speed);
	}
	else
	{
		speed = speed / MB;
		
		sprintf(tspeed,"%I64u MB / s",speed);
	}
	_strSpeed = tspeed;
	return _strSpeed;
}
IUdxTime * GetTimer()
{
	static IUdxTime* pTimer = CreateUdxTime();
	return  pTimer;
}

int execmd(char * cmd,char * result){
	char buffer[128]={0};
	memset(buffer,'\0',128);
	
	FILE* pipe = _popen(cmd,"r");
	
	if(!pipe)
		return 0;//执行错误则返回0
	
	//fread(result,sizeof(char),100,pipe);
	
	while(!feof(pipe)){		
		if (fgets(buffer,128,pipe)) {	

			strcat(result,buffer);		
		}	
	}
	_pclose(pipe);
	//printf("pop\n");
	return 1;
	
}

bool MyListDir(char*szDir,list<string> &listfile,BOOL bdeep)
{

	list<string> listdir;
	string strtopdir = szDir;
	string strdir = szDir;
	string strfile;


	WIN32_FIND_DATA ListFile;//windows的文件属性信息
	HANDLE hListFile;//实体对象类型 内存中的一个实体对象
	char szFilePath[MAX_PATH];
	lstrcpy(szFilePath, szDir);
	lstrcat(szFilePath, "/*");
	hListFile = FindFirstFile(szFilePath, &ListFile);

	if(hListFile != INVALID_HANDLE_VALUE)
	{
		do
		{
			if(lstrcmp(ListFile.cFileName, "..") == 0 || lstrcmp(ListFile.cFileName, ".") == 0)
				continue;
			strfile = ListFile.cFileName;
			if (strstr(strfile.c_str(),".TFHL")!=NULL)
			{
				GetUdxTools()->DBGStr("jump TUDX tmp file--%s%d\n",ListFile.cFileName,strfile.find(".TUDX"));
				continue;
			}

			strdir = strtopdir + "/" + ListFile.cFileName;

			if(ListFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				if(bdeep)
				{
					listdir.push_back(strdir);
//					GetUdxTools()->DBGStr("DIR %s\n",ListFile.cFileName);
				}
			}
			else
			{
				listfile.push_back(strdir);

//				GetUdxTools()->DBGStr("FILE %s\n",ListFile.cFileName);
			}
		}while(FindNextFile(hListFile, &ListFile));

		if(bdeep)
		{
			list<string>::iterator i;
			for (i = listdir.begin();i!=listdir.end();i++)
			{
				MyListDir((char*)(*i).c_str(),listfile,bdeep);
			}
		}
	}
	FindClose(hListFile);
	return true;

}

myTool::myTool(void)
{
	WSADATA wsaData;    
	//返回0 表示初始化成功
	//用于吐出日志
	if(WSAStartup(MAKEWORD(2,2), &wsaData)) {
	  printf("Winsock init fail!/n");      
	  WSACleanup(); 
	}  
	s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	addIn.sin_family = AF_INET;
	addIn.sin_port = htons(LOGPORT);
	addIn.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	
	if(RELEASEFOR == "CH"){
		//设置日志文件名中的时间
		char logfile[255];
		memset(logfile,0,255);
		char m_NowTime[18];
		getNowTimeNoSpace(m_NowTime);
		//random_device rd;
		//mt19937 mt(rd());
		sprintf(logfile,"starttime%s-pid%d.log",m_NowTime,GetCurrentProcessId());
		int i = writeLog()->SetLogFile(logfile);
	}
	

}
myTool::~myTool(void)
{
	WSACleanup(); 	
}
void myTool::printStr(const char* format,...)
{
	char m_NowTime[32];
	getNowTime(m_NowTime);
	va_list argptr;
	va_start(argptr,format);
	char printstr[500]={0};
	memset(printstr,0,sizeof(printstr));
	vsprintf(printstr,format,argptr);
	int bSendRet = sendto(s, printstr, sizeof(printstr), 0, (LPSOCKADDR)&addIn, sizeof(addIn));
	//printf(printstr);
	
	char printstr2[500]={0};
	memset(printstr2,0,sizeof(printstr2));
	if ( RELEASEFOR == "EN")
	{
		sprintf(printstr2,"FHL>> [%s] %s\n",m_NowTime,printstr);
	}else if(RELEASEFOR == "CH"){
		
	}
	
	printf(printstr2);
	va_end(argptr);
	if(RELEASEFOR == "CH"){
		writeLog()->Log(printstr2);
	}
	
}
void myTool::printStrandDB(const char* format,...)
{
	char m_NowTime[32];
	getNowTime(m_NowTime);
	va_list argptr;
	va_start(argptr,format);
	//vprintf(format,argptr);
	char sqlstr[500]={0};
	memset(sqlstr,0,sizeof(sqlstr));
	vsprintf(sqlstr,format,argptr);
	int bSendRet = sendto(s, sqlstr, sizeof(sqlstr), 0, (LPSOCKADDR)&addIn, sizeof(addIn));
	insertLog("eventlog",NULL,sqlstr);
	
	char sqlstr2[500]={0};
	memset(sqlstr2,0,sizeof(sqlstr2));
	if ( RELEASEFOR == "EN")
	{
		sprintf(sqlstr2,"FHL>> [%s] %s\n",m_NowTime,sqlstr);
	}else if(RELEASEFOR == "CH"){
		
		
	}
	printf(sqlstr2);
	va_end(argptr);
	
	if(RELEASEFOR == "CH"){
		writeLog()->Log(sqlstr2);
	}
}

std::wstring myTool::Utf82Unicode(const std::string& utf8string) 
{
    int widesize = ::MultiByteToWideChar(CP_UTF8, 0, utf8string.c_str(), -1, NULL, 0);
    if (widesize == ERROR_NO_UNICODE_TRANSLATION)
    {
        throw std::exception("Invalid UTF-8 sequence.");
    }
    if (widesize == 0)
    {
        throw std::exception("Error in conversion.");
    }
    std::vector<wchar_t> resultstring(widesize);
    int convresult = ::MultiByteToWideChar(CP_UTF8, 0, utf8string.c_str(), -1, &resultstring[0], widesize);
    if (convresult != widesize)
    {
        throw std::exception("La falla!");
    }
    return std::wstring(&resultstring[0]);
}


    //unicode 转为 ascii 
std::string myTool::WideByte2Acsi(std::wstring& wstrcode)
{
    int asciisize = ::WideCharToMultiByte(CP_OEMCP, 0, wstrcode.c_str(), -1, NULL, 0, NULL, NULL);
    if (asciisize == ERROR_NO_UNICODE_TRANSLATION)
    {
        throw std::exception("Invalid UTF-8 sequence.");
    }
    if (asciisize == 0)
    {
        throw std::exception("Error in conversion.");
    }
    std::vector<char> resultstring(asciisize);
    int convresult = ::WideCharToMultiByte(CP_OEMCP, 0, wstrcode.c_str(), -1, &resultstring[0], asciisize, NULL, NULL);
    if (convresult != asciisize)
    {
        throw std::exception("La falla!");
    }
    return std::string(&resultstring[0]);
}



//utf-8 转 ascii 
std::string myTool::UTF_82ASCII(std::string& strUtf8Code)
{
    using namespace std;
    string strRet = "";
    //先把 utf8 转为 unicode 
    wstring wstr = Utf82Unicode(strUtf8Code);
    //最后把 unicode 转为 ascii 
    strRet = WideByte2Acsi(wstr);
    return strRet;
}



//ascii 转 Unicode 
std::wstring myTool::Acsi2WideByte(std::string& strascii)
{
    using namespace std;
    int widesize = MultiByteToWideChar(CP_ACP, 0, (char*)strascii.c_str(), -1, NULL, 0);
    if (widesize == ERROR_NO_UNICODE_TRANSLATION)
    {
        throw std::exception("Invalid UTF-8 sequence.");
    }
    if (widesize == 0)
    {
        throw std::exception("Error in conversion.");
    }
    std::vector<wchar_t> resultstring(widesize);
    int convresult = MultiByteToWideChar(CP_ACP, 0, (char*)strascii.c_str(), -1, &resultstring[0], widesize);
    if (convresult != widesize)
    {
        throw std::exception("La falla!");
    }
    return std::wstring(&resultstring[0]);
}


//Unicode 转 Utf8 
std::string myTool::Unicode2Utf8(const std::wstring& widestring)
{
    using namespace std;
    int utf8size = ::WideCharToMultiByte(CP_UTF8, 0, widestring.c_str(), -1, NULL, 0, NULL, NULL);
    if (utf8size == 0)
    {
        throw std::exception("Error in conversion.");
    }
    std::vector<char> resultstring(utf8size);
    int convresult = ::WideCharToMultiByte(CP_UTF8, 0, widestring.c_str(), -1, &resultstring[0], utf8size, NULL, NULL);
    if (convresult != utf8size)
    {
        throw std::exception("La falla!");
    }
    return std::string(&resultstring[0]);
}


//ascii 转 Utf8 
std::string myTool::ASCII2UTF_8(std::string& strAsciiCode) 
{
    using namespace std;
    string strRet("");
    //先把 ascii 转为 unicode 
    wstring wstr = Acsi2WideByte(strAsciiCode);
    //最后把 unicode 转为 utf8 
    strRet = Unicode2Utf8(wstr);
    return strRet;
}







//myTool getMyTool; 
myTool* getMyTool()
{
	static myTool re; //引用了静态变量
	return &re;
}
 
